package com.yueyang.sojourn.server.controller.wx;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.yueyang.sojourn.server.common.baymax.web.result.JAssert;
import com.yueyang.sojourn.server.controller.BaseController;
import com.yueyang.sojourn.server.controller.model.JsonResult;
import com.yueyang.sojourn.server.model.dto.AddOrderDto;
import com.yueyang.sojourn.server.model.enums.*;
import com.yueyang.sojourn.server.model.po.*;
import com.yueyang.sojourn.server.model.vo.SojournMerchPriceCalculateVo;
import com.yueyang.sojourn.server.model.vo.SojournOrderTimeLineVo;
import com.yueyang.sojourn.server.model.vo.SojournOrderTouristVo;
import com.yueyang.sojourn.server.model.vo.SojournOrderVo;
import com.yueyang.sojourn.server.service.attachdetail.AttachDetailService;
import com.yueyang.sojourn.server.service.member.MemberService;
import com.yueyang.sojourn.server.service.share.ShareDataService;
import com.yueyang.sojourn.server.service.sojourn.merch.ReadMerchService;
import com.yueyang.sojourn.server.service.sojourn.merch.SojournMerchService;
import com.yueyang.sojourn.server.service.sojourn.merch.inventory.MerchInventoryService;
import com.yueyang.sojourn.server.service.sojourn.merchant.SojournMerchantService;
import com.yueyang.sojourn.server.service.sojourn.order.SojournOrderEventService;
import com.yueyang.sojourn.server.service.sojourn.order.SojournOrderMsgService;
import com.yueyang.sojourn.server.service.sojourn.order.SojournOrderService;
import com.yueyang.sojourn.server.service.sojourn.order.SojournOrderTouristService;
import com.yueyang.sojourn.server.service.sojourn.sequence.SojournSequnceManager;
import com.yueyang.sojourn.server.service.sojourn.tourist.SojournTouristService;
import com.yueyang.uc.model.UcUserV1;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author andy.yang
 * @version v1
 * @summary
 * @Copyright (c) 2019, yueyang Group All Rights Reserved.
 * @since 2020/3/17
 */
@Slf4j
@RestController
@RequestMapping("/api/wx/order")
@Api(tags = "(小程序)订单 API")
public class ApiOrderController extends BaseController {

    @Autowired
    SojournOrderService orderService;
    @Autowired
    SojournMerchService merchService;
    @Autowired
    ReadMerchService readMerchService;
    @Autowired
    MerchInventoryService merchInventoryService;
    @Autowired
    SojournOrderTouristService orderTouristService;
    @Autowired
    SojournTouristService touristService;
    @Autowired
    private AttachDetailService attachDetailService;
    @Autowired
    private SojournOrderEventService orderEventService;
    @Autowired
    SojournSequnceManager sojournSequnceManager;
    @Autowired
    private MemberService memberService;
    @Autowired
    SojournOrderMsgService orderMsgService;
    @Autowired
    SojournMerchantService merchantService;
    @Autowired
    private ShareDataService shareDataService;

    /**
     * 下订单
     *
     * @param orderDto
     * @return
     */
    @ApiImplicitParam(name = "X-Token", paramType = "header", required = true)
    @ApiOperation(value = "下订单")
    @PostMapping("")
    public JsonResult<Long> createOrder(@RequestHeader(value = "shareId", required = false) Long shareId, @RequestBody @Validated AddOrderDto orderDto,
                                        BindingResult bindingResult,
                                        HttpServletResponse response) {
        FieldError fieldError = bindingResult.getFieldError();
        if (Objects.nonNull(fieldError)) {
            JAssert.justFailed(fieldError.getDefaultMessage());
        }

        UcUserV1 ucUserV1 = super.getLoginUser();
        long loginUserId = ucUserV1.getId();

        //参数业务验证
        SojournMerch merch = merchService.selectByPrimaryKey(orderDto.getMerchId());
        if (merch == null) {
            return fail("商品不存在");
        }

        if (merch.getShelfStatus() != ShelfStatusEnum.BEING_ON.getCode()) {
            return fail("商品已下架");
        }

        List<SojournTourist> tourists = touristService.findByIds(orderDto.getTouristIds());
        if (tourists.isEmpty()) {
            return fail("游客不存在");
        }
        Map<Long, SojournTourist> touristMap = tourists.stream().collect(Collectors.toMap(SojournTourist::getId, a -> a, (k1, k2) -> k1));
        for (Long touristId : orderDto.getTouristIds()) {
            if (!touristMap.keySet().contains(touristId) || !touristMap.get(touristId).getCreator().equals(loginUserId)) {
                return fail("游客不存在");
            }
        }
        if (orderDto.getMerchEffectDate().before(merch.getAvailableDateBegin())
                || orderDto.getMerchEffectDate().after(merch.getAvailableDateEnd())) {
            return fail("超出了有效期");
        }
        //检查当前商品是否绑定了商户
        SojournMerchant merchant = merchantService.findByProjectId(merch.getProjectId());
        if (merchant == null) {
            return fail("请联系管理员为商品绑定商户");
        }

        SojournOrder order = new SojournOrder();
        BeanUtils.copyProperties(orderDto, order);

        //冗余图片
        List<AttachDetail> attachDetails = attachDetailService.selectListByMerchId(merch.getId());
        order.setMerchTitle(merch.getTitle());
        if (attachDetails != null && !attachDetails.isEmpty()) {
            order.setMerchPicAttachId(attachDetails.get(0).getId());
        }
        //冗余下单人信息
        order.setCreatorName(ucUserV1.getNickName());
        order.setCreatorPhone(ucUserV1.getPhone());
        //冗余商品项目id
        order.setMerchProjectId(merch.getProjectId());
        order.setCreator(loginUserId);
        order.setMerchCount(orderDto.getTouristIds().size());
        //获取商品订单最终的优惠；（如：当前用户如果不是vip，则不享受此优惠）
        List<MerchSaleTypeEnum> saleTypeEnums = readMerchService.getMerchRealSales(JSON.parseArray(merch.getSale(), Integer.class), memberService.isMember(ucUserV1.getId()));
        List<Integer> realSales = new ArrayList<>();
        if (saleTypeEnums != null && !saleTypeEnums.isEmpty()) {
            saleTypeEnums.stream().forEach((sale) -> realSales.add(sale.getCode()));
        }
        order.setMerchSale(JSON.toJSONString(realSales));
        SojournMerchPriceCalculateVo priceVo = readMerchService.calculateMerchPrice(merch, order.getMerchCount(), null, memberService.isMember(ucUserV1.getId()));
        order.setMerchPrice(new BigDecimal(merch.getPrice()));
        order.setDiscountOnePrice(priceVo.getDiscountOnePrice());
        order.setTotalPrice(priceVo.getFinalPrice());
        order.setDiscounted(priceVo.getDiscountedPrice());
        order.setStatus(OrderStatusEnum.TO_BE_PAY.getCode());
        order.setSn(sojournSequnceManager.nextValueOfOrder(OrderTypeEnum.MERCH));

        // 先占库存
        merchInventoryService.takeInventory(order.getCreator(), order.getSn(), order.getMerchId(), order.getMerchEffectDate(), null, orderDto.getTouristIds().size());

        Long orderId = orderService.add(order, orderDto.getTouristIds());
        JsonResult rs = JsonResult.ok();
        rs.setData(orderId);


        // 下单分销行为数据
        if (shareId != null) {
            shareDataService.action(shareId, ShareDataTypeEnum.下单, getLoginUserId(), "创建了商品订单", orderId);
        }
        return rs;
    }

    /**
     * 撤销订单
     *
     * @param orderId
     * @return
     */
//    @ApiOperation(value = "撤销订单")
//    @ApiImplicitParam(name = "X-Token", paramType = "header", required = true)
//    @DeleteMapping("/{orderId}")
//    public JsonResult<SojournOrderVo> cancelOrder(@ApiParam(value = "订单id") @PathVariable Long orderId) {
//
//        return null;
//    }

    /**
     * 我的订单
     *
     * @param status
     * @return
     */
    @ApiImplicitParam(name = "X-Token", paramType = "header", required = true)
    @ApiOperation(value = "我的订单")
    @GetMapping("/mine")
    public PageInfo<SojournOrderVo> myOrder(@ApiParam(value = "订单状态:不传代表全部") @RequestParam(required = false) Integer status,
                                            @RequestParam int pageNo,
                                            @RequestParam int pageSize) {
        UcUserV1 ucUserV1 = super.getLoginUser();
        long loginUserId = ucUserV1.getId();
        PageInfo<SojournOrder> pageInfo = orderService.findPage(loginUserId, null, null,
                null, status, OrderTypeEnum.MERCH.getCode(),pageNo, pageSize);

        PageInfo<SojournOrderVo> page = new PageInfo<>();
        BeanUtils.copyProperties(pageInfo, page);
        page.setList(pageInfo.getList().parallelStream()
                .map(po -> {
                    SojournOrderVo vo = new SojournOrderVo();
                    BeanUtils.copyProperties(po, vo);
                    vo.setMerchSales(JSON.parseArray(po.getMerchSale(), Integer.class));
                    Long now = System.currentTimeMillis();
                    Long remainTime = now > po.getPayEndTime().getTime() ? 0 : (po.getPayEndTime().getTime() - now) / 1000;
                    vo.setPayRemainTime(remainTime);
                    return vo;
                })
                .collect(Collectors.toList()));
        return page;
    }

    /**
     * 订单详情
     *
     * @param orderId
     * @return
     */
    @ApiImplicitParam(name = "X-Token", paramType = "header", required = true)
    @ApiOperation(value = "订单详情")
    @GetMapping("/{orderId}")
    public SojournOrderVo orderDetail(@ApiParam(value = "订单id") @PathVariable Long orderId, HttpServletResponse response) {
        UcUserV1 ucUserV1 = super.getLoginUser();
        long loginUserId = ucUserV1.getId();
        SojournOrder order = orderService.findById(orderId);
        if (order == null || !order.getCreator().equals(loginUserId)) {
            return null;
        }
        SojournOrderVo orderVo = new SojournOrderVo();
        BeanUtils.copyProperties(order, orderVo);
        orderVo.setMerchSales(JSON.parseArray(order.getMerchSale(), Integer.class));
        Long now = System.currentTimeMillis();
        Long remainTime = now > orderVo.getPayEndTime().getTime() ? 0 : (orderVo.getPayEndTime().getTime() - now) / 1000;
        orderVo.setPayRemainTime(remainTime);
        List<SojournOrderTourist> orderTouristList = orderTouristService.findByOrderId(orderId);
        List<SojournOrderTouristVo> orderTouristVos = new ArrayList();
        orderTouristList.stream().forEach((orderTourist) -> {
            SojournOrderTouristVo vo = new SojournOrderTouristVo();
            BeanUtils.copyProperties(orderTourist, vo);
            if (CardTypeEnum.ID.getCode() == vo.getCardType() && vo.getCardNo() != null && !vo.getCardNo().isEmpty()) {
                vo.setCardNo(vo.getCardNo().substring(0, 6) + "********"
                        + vo.getCardNo().substring(vo.getCardNo().length() - 4));
            }
            orderTouristVos.add(vo);
        });
        orderVo.getOrderTourists().addAll(orderTouristVos);
        return orderVo;
    }

    /**
     * 订单时间线
     *
     * @param orderId
     * @return
     */
    @ApiImplicitParam(name = "X-Token", paramType = "header", required = true)
    @ApiOperation(value = "订单时间线")
    @GetMapping("/{orderId}/timeline")
    public List<SojournOrderTimeLineVo> orderTimeLine(@ApiParam(value = "订单id") @PathVariable Long orderId,
                                                      @ApiParam(value = "时间线类型：1-成交 2-退款") @RequestParam("type") Integer type) {
        List<SojournOrderTimeLineVo> timeLineVos = new ArrayList<>();
        List<SojournOrderEvent> events = orderEventService.findByOrderId(orderId);
        if(type == null || (type != 1 && type != 2)){
            return null;
        }

        List<SojournOrderTimeLineVo.TimeLineNode> timeLineStrategy = SojournOrderTimeLineVo.getTimeLineStrategy(type);

        for (SojournOrderTimeLineVo.TimeLineNode timeLineNode : timeLineStrategy) {
            for (SojournOrderEvent event : events) {
                if (timeLineNode.getOrderEventType().getCode() == event.getType()) {
                    SojournOrderTimeLineVo vo = new SojournOrderTimeLineVo();
                    vo.setCreatedTime(event.getCreatedTime());
                    vo.setCreator(event.getCreator());
                    vo.setShowDesc(timeLineNode.getDesc());
                    timeLineVos.add(vo);
                    break;
                }
            }
        }

        if (timeLineVos.size() > 0) {
            timeLineVos.get(0).setCurrent(true);
        }
        return timeLineVos;
    }

    @ApiImplicitParam(name = "X-Token", paramType = "header", required = true)
    @ApiOperation(value = "商品下单前库存剩余检验", notes = "true-有剩余库存；false-库存不足；")
    @GetMapping("/checkInventory")
    public boolean checkInventory(@ApiParam(value = "商品id") @RequestParam long merchId,
                                  @ApiParam(value = "出行日期(yyyy-MM-dd)", example = "2020-02-20") @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date merchEffectDate,
                                  @ApiParam(value = "出行人数") @RequestParam int count) {
        return count <= merchInventoryService.calcRemnantInventory(merchId, merchEffectDate, null);
    }
}
